﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\Automata\DFA\DfaConstructor.cs
 * Description  :     Constructing a DFA
 * Change log   :     
 * To Do        :     
 ************************************************************************/
using System;
using System.Collections.Generic;
using SMLib.Automata.Base;

namespace SMLib.Automata.DFA
{
    /// <summary>
    /// Construct a DFA
    /// </summary>
    public class DfaConstructor
    {
        DFA myDFA;
        Alphabet Sigma;
        /// <summary>
        /// Constructor
        /// </summary>
        public DfaConstructor()
        {
            Sigma = new Base.Alphabet();
            myDFA = new DFA(Sigma);
        }

        /// <summary>
        /// Set a state as accepting
        /// </summary>
        /// <param name="node">id of the state</param>
        public void SetAsAccepting(string node)
        {
            DFA.DFA_State srcSt = null;
            foreach (DFA.DFA_State st in myDFA.GetAllStates())
            {
                if (st.Identifier.Equals(node))
                {
                    srcSt = st;
                    break;
                }
            }
            if (srcSt != null)
            {
                srcSt.isAccepting = true;
            }
            else
                throw new Exception("State not found!");
        }

        /// <summary>
        /// Set a state as rejecting
        /// </summary>
        /// <param name="node">id of the state</param>
        public void SetAsRejecting(string node)
        {
            DFA.DFA_State srcSt = null;
            foreach (DFA.DFA_State st in myDFA.GetAllStates())
            {
                if (st.Identifier.Equals(node))
                {
                    srcSt = st;
                    break;
                }
            }
            if (srcSt != null)
            {
                srcSt.isAccepting = false;
            }
            else
                throw new Exception("State not found!");
        }

        /// <summary>
        /// Add a transition to DFA
        /// </summary>
        /// <param name="src">id of source state</param>
        /// <param name="dst">id of destination state</param>
        /// <param name="edge">label of edge</param>
        public void AddEdge(string src, string dst, string edge)
        {
            StringSymbol currEdge = new StringSymbol(edge);
            if (Sigma.Contains(currEdge))
                Sigma.AddSymbol(currEdge);
            DFA.DFA_State srcSt = null, dstSt = null;
            foreach (DFA.DFA_State st in myDFA.GetAllStates())
            {
                if (st.Identifier.Equals(src))
                    srcSt = st;
                if (st.Identifier.Equals(src))
                    dstSt = st;
                if (dstSt != null && srcSt != null)
                    break;
            }
            if (dstSt == null)
            {
                dstSt = new DFA.DFA_State(dst);
            }
            if (srcSt == null)
            {
                srcSt = new DFA.DFA_State(src);
            }
            srcSt.Transitions.Add(new DFA.DFA_Transition(currEdge));
        }


        /// <summary>
        /// Generate the DFA
        /// </summary>
        /// <returns>the generated DFA</returns>
        public DFA Generate()
        {
            return myDFA;
        }
    }
}
